#include "voice_common.h"

#if (defined(GKT_CONFIG_VOICE_OUTPUT_ENABLE) && GKT_CONFIG_VOICE_OUTPUT_ENABLE) \
	(!defined(GKT_CONFIG_VOICE_OUTPUT_RES_MAP_READ) || !GKT_CONFIG_VOICE_OUTPUT_RES_MAP_READ)

int voice_output_next_meta(voice_output_s *output)
{
	gkt_voice_meta_id_t meta_id;
	uint32_t meta_data_size;
	int retval;

	output->meta_left_frame_nums = 0;
	output->meta_id_index++;
	while (output->meta_id_index < output->combined_attr->meta_nums) {
		meta_id = output->combined_attr->meta_ids[output->meta_id_index];
		if (meta_id < output->c_header->meta_nums) {
			meta_data_size = output->c_meta_attrs[meta_id].data_size;
			if (output->v_meta_buffer 
				&& (meta_data_size > output->meta_buffer_size)) 
			{
				gkt_free(output->v_meta_buffer);
				output->v_meta_buffer = NULL;
			}

			if (!output->v_meta_buffer) {
				meta_data_size = (meta_data_size + 0xff) & (~0xff);
				output->v_meta_buffer = (uint8_t *)gkt_malloc(meta_data_size);
				if (!output->v_meta_buffer) {
					gkt_error("voice_output: alloc meta buffer failed.\n");
					return GKT_ENOMEMORY;
				}
				output->meta_buffer_size = meta_data_size;
			}

			retval = gkt_flash_read(output->c_flash_info->id,
							output->meta_data_base_offset + output->c_meta_attrs[meta_id].data_offset,
							output->c_meta_attrs[meta_id].data_size, output->v_meta_buffer);
			if (retval != GKT_SUCCESS) {
				gkt_error("voice_output: read meta data failed.\n");
				return retval;
			}

#if !GKT_VOICE_DEC_INPUT_FRAME_SIZE
			output->meta_left_frame_nums = output->c_meta_attrs[meta_id].frame_nums;
#else
			output->meta_left_frame_nums = output->c_meta_attrs[meta_id].data_size / GKT_VOICE_DEC_INPUT_FRAME_SIZE;
#endif
			if (output->meta_left_frame_nums)
				break;
		}

		output->meta_id_index++;
	}

	voice_output_decode_append_frames(output);

	return GKT_SUCCESS;
}

int voice_output_init_resource(voice_output_s *output)
{
	voice_output_partition_header_s *header;
	voice_output_meta_attr_s *meta_attrs;
	uint32_t total_size;
	int retval = GKT_SUCCESS;

	output->c_header = NULL;
	output->c_meta_attrs = NULL;

	output->c_flash_info = gkt_flash_partition_get_info(GKT_CONFIG_VOICE_OUTPUT_RES_PARTITION_NAME);
	if (__UNLIKELY(!output->c_flash_info)) {
		gkt_error("voice_output: voice res partition does not exist!\n");
		retval = GKT_ENOTEXIST;
	}
	else if (__UNLIKELY(!output->c_flash_info->read_map_addr)) {
		gkt_error("voice_output: not mapped flash.\n");
		retval = GKT_EUNMATCHED;
	}
	else {
		header = (voice_output_partition_header_s *)gkt_malloc(VOICE_OUTPUT_PARTITION_HEADER_SIZE);
		if (!header) {
			gkt_error("voice_output: alloc part header failed!\n");
			return GKT_ENOMEMORY;
		}

		retval = gkt_flash_read(output->c_flash_info->id, 
					0, VOICE_OUTPUT_PARTITION_HEADER_SIZE, header);
		if (retval != GKT_SUCCESS) {
			gkt_error("voice_output: read part header failed!\n");
			gkt_free(header);
			return retval;
		}

		output->c_header = (const voice_output_partition_header_s *)header;
		if ((VOICE_OUTPUT_PART_MAGIC == output->c_header->magic)
			&& (output->c_header->meta_nums <= GKT_VOICE_OUTPUT_META_MAXNUMS)
			&& (output->c_header->meta_data_totalsize <= VOICE_OUTPUT_META_DATA_TOTALSIZE)) 
		{
			total_size = VOICE_OUTPUT_PARTITION_HEADER_SIZE 
						+ (output->c_header->meta_nums * VOICE_OUTPUT_META_ATTR_SIZE)
						+ output->c_header->meta_data_totalsize;
			if (total_size > output->c_flash_info->size) {
				gkt_error("voice_output: flash partition space is INSUFFICIENT.\n");
				return GKT_EUNMATCHED;
			}

			gkt_trace("voice_output: meta_nums(%u), totalsize(%u)\n",
							output->c_header->meta_nums, 
							output->c_header->meta_data_totalsize);
		}
		else {
			gkt_info("voice_output: voice resource invalid.\n");
			return GKT_EUNMATCHED;
		}

		total_size = sizeof(voice_output_meta_attr_s) * output->c_header->meta_nums;
		meta_attrs = (voice_output_meta_attr_s *)gkt_malloc(total_size);
		if (!meta_attrs) {
			gkt_error("voice_output: alloc meta attrs failed!\n");
			return GKT_ENOMEMORY;
		}

		retval = gkt_flash_read(output->c_flash_info->id, 
					VOICE_OUTPUT_PARTITION_HEADER_SIZE, total_size, meta_attrs);
		if (retval != GKT_SUCCESS) {
			gkt_error("voice_output: read meta attrs failed!\n");
			gkt_free(meta_attrs);
			return retval;
		}

		output->meta_data_base_offset = VOICE_OUTPUT_PARTITION_HEADER_SIZE + total_size;
	}

	return retval;
}

#endif

